package travianBot;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import org.apache.log4j.Logger;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

import test.TestTravianScriptRunner;


public class Village {
	static Logger log=Logger.getLogger(Village.class);
	
	public static final String NEWLINE = System.getProperty("line.separator");
	
	private int id;
	private String name;
	private boolean attackFlag = false;
	
	public static final String CLAY_PIT		= "Clay Pit";
	public static final String WHEAT_FIELD	= "Wheat Field";
	public static final String WOODCUTTER	= "Woodcutter";
	public static final String IRON_MINE	= "Iron Mine";
	
	public static final String[] RESOURCE_NAME_ARRAY = {CLAY_PIT, WHEAT_FIELD, WOODCUTTER, IRON_MINE};
	
	public static final String HORSE_DRINKING_TROUGH	= "Horse Drinking Trough";
	public static final String STABLE	= "Stable";
	public static final String HEROS_MANSION = "Hero's Mansion";
	public static final String CITY_WALL = "City Wall";
	public static final String MARKETPLACE = "Marketplace";
	public static final String ARMORY = "Armoury";
	
	public static final int NAME_FIELS_SIZE=20;
	public static final int MIN_BUILDING_PLOT=19;
	public static final int MAX_BUILDING_PLOT=40;
	
	public ArrayList<ResourceEntry> resourceList = new ArrayList<ResourceEntry>();
	public ArrayList<ResourceEntry> buildingList = new ArrayList<ResourceEntry>();
	HashMap<String, ResourceCounter> resourceCounters = null;
	
	public Village(int id, String name){
		this.id = id;
		this.name = name;
	}

	public boolean isLoaded(){
		return resourceList.size() > 0;
	}
	
	/**
	 * collect the details about the buildings
	 * @param htmlString
	 * @return
	 * @throws TravianBotException
	 */
	public ArrayList<ResourceEntry> initialiseBuildings(String htmlString) throws TravianBotException{
		HtmlCleaner htmlCleaner = new HtmlCleaner();		
		
		try {
			TagNode parentNode = htmlCleaner.clean(htmlString);
			Object[] nodeArray = parentNode.evaluateXPath("//area");
			
			String  href;
			String  title;
			for (int i = 0; i < nodeArray.length-1; i++) {
				//the last link is the village center
				TagNode mapNode = (TagNode)nodeArray[i];
				// {href=build.php?id=1, coords=101,33,28, shape=circle, title=Woodcutter level 12}
				
				// find the location(id)
				href = mapNode.getAttributeByName("href");				
				// use a regex to collect the pieces needed
				String[] locationSplit = href.split("=");
				String  location = locationSplit[1];
				
				// find the resource level
				title = mapNode.getAttributeByName("title");
				String[] titleSplitArray = title.split("level");
				int level = 0;
				String type = "Building Site";
				if(titleSplitArray.length > 1){
					level = Integer.parseInt(titleSplitArray[titleSplitArray.length-1].trim());
					type = titleSplitArray[0].trim();
				}
				
				ResourceEntry re = new ResourceEntry(location, type, level);
				buildingList.add(re);
			}
		} catch (Exception e) {
			throw new TravianBotException("problems while initialising buildings",e);
		}	
		
		return buildingList;
	}
	
	/**
	 * collect the correct building resource entry
	 * @param buildingName
	 * @return
	 */
	public ResourceEntry getBuildingResourceEntry(String buildingName){
		ResourceEntry returnResourceEntry = null;
		for (ResourceEntry resourceEntry : buildingList) {
			if(resourceEntry.type.equals(buildingName)){
				if(returnResourceEntry == null){
					returnResourceEntry = resourceEntry;
				}else if(returnResourceEntry.level > resourceEntry.level){
					returnResourceEntry = resourceEntry;
				}				
			}
		}
		return returnResourceEntry;
	}
	
	/**
	 * collect the details of a village resources from the html
	 * @param htmlString
	 * @throws TravianBotException 
	 */
	public ArrayList<ResourceEntry> initialiseResources(String htmlString) throws TravianBotException{
		HtmlCleaner htmlCleaner = new HtmlCleaner();		
		
		try {
			TagNode parentNode = htmlCleaner.clean(htmlString);
			Object[] nodeArray = parentNode.evaluateXPath("//area");
						
			String  href;
			String  title;
			for (int i = 0; i < nodeArray.length-1; i++) {
				//the last link is the village center
				TagNode mapNode = (TagNode)nodeArray[i];
				// {href=build.php?id=1, coords=101,33,28, shape=circle, title=Woodcutter level 12}
				
				// find the location(id)
				href = mapNode.getAttributeByName("href");				
				// use a regex to collect the pieces needed
				String[] locationSplit = href.split("=");
				String  location = locationSplit[1];
				
				
				// find the resource level
				title = mapNode.getAttributeByName("title");											
				String[] titleSplitArray = title.split("level");
				int level = Integer.parseInt(titleSplitArray[titleSplitArray.length-1].trim());
				
				//find the resource type
				String type = titleSplitArray[0].trim();
				if(titleSplitArray.length == 4){
					// some names have a space
					type += " "+ titleSplitArray[1];
				}
				
				ResourceEntry re = new ResourceEntry(location, type, level);
				resourceList.add(re);
			}
		} catch (Exception e) {
			log.error("problems while initialising villages");
			throw new TravianBotException("problems while initialising villages",e);
		}	
		
		//
		// get the resource levels
		//		
		try {
			this.resourceCounters = getResourcesCounters(htmlString);
		} catch (Exception e) {
			log.error("problems collecting resource counters");
			throw new TravianBotException("problems collecting resource counters",e);
		}
		
		return resourceList;
	}
	
	public String getResourceCountersString(){
		StringBuilder out = new StringBuilder();
		
		if(this.resourceCounters != null){
			for (int i = 0; i < RESOURCE_NAME_ARRAY.length; i++) {
				String key = RESOURCE_NAME_ARRAY[i];
				ResourceCounter resourceCounter = this.resourceCounters.get(key);
				out.append(" "+key+"="+resourceCounter);			
			}
		}
		return out.toString();
	}
	
	public String getResourceCountersCSVString(){
		StringBuilder out = new StringBuilder();
		SimpleDateFormat dateFormat = new SimpleDateFormat("yy-MM-dd");
		SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
		Date now = new Date();
		String dateString = dateFormat.format(now);
		String timeString = timeFormat.format(now);
				
		if(this.resourceCounters != null){
			for (int i = 0; i < RESOURCE_NAME_ARRAY.length; i++) {
				String key = RESOURCE_NAME_ARRAY[i];
				ResourceCounter resourceCounter = this.resourceCounters.get(key);
				//out.append(" "+key+"="+resourceCounter);
				String resourceType = TravianBotUtil.stringPad(key," ",NAME_FIELS_SIZE-key.length());
				String villageName = TravianBotUtil.stringPad(this.name," ",11-this.name.length());
				out.append(dateString+","+timeString+","+villageName+","+resourceType+","+resourceCounter.getCSV()).append(NEWLINE);
			}
		}
		return out.toString();
	}
	
	public HashMap<String,ResourceCounter> getResourcesCounters(String htmlString) throws TravianBotException, IOException{
		HtmlCleaner htmlCleaner = new HtmlCleaner();
		ResourceCounter resourceCounter = null;
		HashMap<String,ResourceCounter> returnMap = new HashMap<String,ResourceCounter>();
		//<div id="res">
		try {
			TagNode parentNode = htmlCleaner.clean(htmlString);
			Object[] nodeArray = parentNode.evaluateXPath("//div[@id='res']/table/tbody/tr/td");
			StringBuffer	nodeText;
			String[]		resourceTokens;
			for (int i = 0; i < nodeArray.length; i++) {
				TagNode resourceTDNode = (TagNode)nodeArray[i];	

				Object[] tdEntryArray;
				String key=null;
				if((tdEntryArray = resourceTDNode.evaluateXPath("//img[@title='Wood']")).length != 0){
					key=WOODCUTTER;						
				}else if((tdEntryArray = resourceTDNode.evaluateXPath("//img[@title='Clay']")).length != 0){
					key=CLAY_PIT;	
				}else if((tdEntryArray = resourceTDNode.evaluateXPath("//img[@title='Iron']")).length != 0){
					key=IRON_MINE;	
				}else if((tdEntryArray = resourceTDNode.evaluateXPath("//img[@title='Wheat']")).length != 0){
					key=WHEAT_FIELD;	
				}
				if(key != null){
					nodeText = ((TagNode)nodeArray[i+1]).getText();
					resourceTokens = nodeText.toString().split("/");
					resourceCounter = new ResourceCounter(key, Integer.parseInt(resourceTokens[0]), Integer.parseInt(resourceTokens[1]));
					returnMap.put(key, resourceCounter);		
				}
			}
			
		}catch (XPatherException e) {
			throw new TravianBotException("problems collecting village resource counters",e);
		}catch (IOException ioe){
			throw new TravianBotException("problems collecting village resource counters",ioe);
		}
		return returnMap;
	}	
	
	public ResourceEntry getLowestLevelResource(String resourceType){
		ResourceEntry bestResource = null;
		for (ResourceEntry resourceEntry : this.resourceList) {			
			if(resourceEntry.type.equals(resourceType)){				
				if(bestResource == null){
					bestResource = resourceEntry;
				}else if(resourceEntry.level < bestResource.level){
					bestResource = resourceEntry;
				}
			}
		}
		return bestResource;
	}
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public boolean getAttackFlag() {
		return attackFlag;
	}

	public void setAttackFlag(boolean attackFlag) {
		this.attackFlag = attackFlag;
	}

	public ArrayList<ResourceEntry> getResourceList() {
		return resourceList;
	}

	public HashMap<String, ResourceCounter> getResourceCounters() {
		return resourceCounters;
	}
	
	
}
